package com.jie.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jie.dao.GoodsDao;
import com.jie.entity.Goods;
import com.jie.entity.GoodsAttrs;
import com.jie.entity.QuerInfo;
import com.jie.mapper.GoodsAttrsMapper;
import com.jie.mapper.GoodsMapper;
import com.jie.service.GoodsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.jie.utility.FrontInfo;
import com.jie.utility.QueryInfo;
import com.jie.utility.R;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author jie
 * @since 2024-01-16
 */
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements GoodsService {
    @Autowired
    private  GoodsMapper goodsMapper;
    @Autowired
    private GoodsAttrsMapper attrsMapper;
    @Autowired
    private RestHighLevelClient client;

    @Override
    public R<List<GoodsDao>> goods(QueryInfo queryInfo,Integer adminId) {
        LambdaQueryWrapper<Goods> queryWrapper = new LambdaQueryWrapper<>();
        Page page = new Page<>(queryInfo.getPagenum(), queryInfo.getPagesize());
        queryWrapper.like(StringUtils.isNotEmpty(queryInfo.getQuery()),Goods::getGoodsName,"%"+queryInfo.getQuery()+"%");
        if(adminId!=1){
            queryWrapper.eq(Goods::getCreateAdminId,adminId);
        }
        goodsMapper.selectPage(page,queryWrapper);
        List<GoodsDao> goodsDaos=new ArrayList<>();
        Map<String,Long> map=new HashMap<>();
        map.put("total",page.getTotal());
        if(page.getRecords()!=null){
            for (Object record : page.getRecords()) {
                GoodsDao goodsDao = new GoodsDao();
                Goods goods = JSON.parseObject(JSON.toJSONString(record), Goods.class);
                BeanUtils.copyProperties(goods,goodsDao);
                LambdaQueryWrapper<GoodsAttrs> wrapper = new LambdaQueryWrapper<>();
                LambdaQueryWrapper<GoodsAttrs> queryWrapper1 = new LambdaQueryWrapper<>();
                wrapper.eq(GoodsAttrs::getGoodsId,goods.getGoodsId());
                wrapper.eq(GoodsAttrs::getIsMany,1);
                queryWrapper1.eq(GoodsAttrs::getGoodsId,goods.getGoodsId());
                queryWrapper1.eq(GoodsAttrs::getIsMany,0);
                List<GoodsAttrs> manyAttrs = attrsMapper.selectList(wrapper);
                List<GoodsAttrs> onlyAttrs = attrsMapper.selectList(queryWrapper1);
                goodsDao.setManyAttrs(manyAttrs);
                goodsDao.setOnlyAttrs(onlyAttrs);
                goodsDaos.add(goodsDao);
            }
            return R.success(goodsDaos,map);
        }
        return R.success(goodsDaos,map);

    }

    @Override
    public R<GoodsDao> goodsByid(String id) {
        GoodsDao goodsDao = new GoodsDao();
        Goods goods = goodsMapper.selectById(id);
        BeanUtils.copyProperties(goods,goodsDao);
        LambdaQueryWrapper<GoodsAttrs> wrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<GoodsAttrs> queryWrapper = new LambdaQueryWrapper<>();
        wrapper.eq(GoodsAttrs::getGoodsId,goods.getGoodsId());
        wrapper.eq(GoodsAttrs::getIsMany,1);
        queryWrapper.eq(GoodsAttrs::getGoodsId,goods.getGoodsId());
        queryWrapper.eq(GoodsAttrs::getIsMany,0);
        List<GoodsAttrs> manyAttrs = attrsMapper.selectList(wrapper);
        List<GoodsAttrs> onlyAttrs = attrsMapper.selectList(queryWrapper);
      goodsDao.setManyAttrs(manyAttrs);
      goodsDao.setOnlyAttrs(onlyAttrs);
        return R.success(goodsDao);
    }

    @Override
    public R<List<GoodsDao>> goodsByES(FrontInfo queryInfo) throws IOException {

        SearchRequest request = new SearchRequest("goods");
        if(queryInfo.getQuery()!=null&&queryInfo.getQuery().length()>0){
            request.source().query(QueryBuilders.matchQuery("goodsName",queryInfo.getQuery()));
        }
        if(queryInfo.getGoodsCat()!=null&&queryInfo.getGoodsCat().length()>0){
            request.source().query(QueryBuilders.termQuery("goodsCat",queryInfo.getGoodsCat()));
        }
        if(queryInfo.getSortName().equals("all")||queryInfo.getSortName().equals(" ")){
            if(!queryInfo.getSortName().equals(" ")) {
                if (queryInfo.getSort().equals("asc")) {
                    request.source().sort(SortBuilders.fieldSort("quantitySold").order(SortOrder.ASC));
                    request.source().sort(SortBuilders.fieldSort("star").order(SortOrder.ASC));
                    request.source().sort(SortBuilders.fieldSort("goodsPrice").order(SortOrder.ASC));
                } else {
                    request.source().sort(SortBuilders.fieldSort("quantitySold").order(SortOrder.DESC));
                    request.source().sort(SortBuilders.fieldSort("star").order(SortOrder.DESC));
                    request.source().sort(SortBuilders.fieldSort("goodsPrice").order(SortOrder.DESC));
                }
            }
        }else {
            if(queryInfo.getSort().equals("asc")){
                request.source().sort(queryInfo.getSortName(),SortOrder.ASC);
            }else {
                request.source().sort(queryInfo.getSortName(),SortOrder.DESC);
            }
        }
        double maxPrice=0,minPrice=0;
        if(!queryInfo.getMaxPrice().isEmpty()){
            maxPrice=Double.parseDouble(queryInfo.getMaxPrice());
        }
      if(!queryInfo.getMinPrice().isEmpty()){
          minPrice=Double.parseDouble(queryInfo.getMinPrice());
      }

if(minPrice!=0||maxPrice!=0){
    if(maxPrice!=0){
        request.source().query(QueryBuilders.rangeQuery("goodsPrice").gte(minPrice).lte(maxPrice));
    }else {
        request.source().query(QueryBuilders.rangeQuery("goodsPrice").gte(minPrice));
    }

}
        request.source().from((queryInfo.getPagenum()-1)*queryInfo.getPagesize()).size(queryInfo.getPagesize());
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        return getListR(response);
    }

    /**
     * 前端根据id查询es的商品信息
     * @param id
     * @return
     */
    @Override
    public GoodsDao findidfigure(String id) {
        GoodsDao goodsDao=null;
        try {
            GetRequest request = new GetRequest("goods").id(id);
            GetResponse response = client.get(request, RequestOptions.DEFAULT);
            if (response.isExists()) {
                String json = response.getSourceAsString();
                 goodsDao=JSON.parseObject(json,GoodsDao.class);
            }
            return goodsDao;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<String> mySuggestion(String name) {

        try {
            List<String> inputs=new ArrayList<>();
            SearchRequest request=new SearchRequest("goods");
            request.source().suggest(new SuggestBuilder().addSuggestion("mySuggestion",
                    SuggestBuilders.completionSuggestion("suggestion")
                            .prefix(name)
                            .skipDuplicates(true)
                            .size(10)
            ));
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            Suggest suggest = response.getSuggest();
            CompletionSuggestion suggestion= suggest.getSuggestion("mySuggestion");
            for (CompletionSuggestion.Entry.Option option : suggestion.getOptions()) {
             inputs.add(option.getText().toString());
            }
            return inputs;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 解析数据结构
     * @param response
     * @return
     */
    @Override
    public R<List<GoodsDao>> getListR(SearchResponse response) {
        SearchHits searchHits = response.getHits();
        long total =searchHits.getTotalHits().value;
        SearchHit[] hits=searchHits.getHits();
        List<GoodsDao> goodsDaoList=new ArrayList<>();
        Map map=new HashMap<>();
        map.put("total",total);
        for(SearchHit hit:hits){
            String json= hit.getSourceAsString();
            GoodsDao goodsDao=JSON.parseObject(json,GoodsDao.class);
            goodsDaoList.add(goodsDao);
        }
        return R.success(goodsDaoList,map);
    }

    @Override
    public List<GoodsDao> getGoodsforAdmin(Goods goods) {
        LambdaQueryWrapper<Goods> queryWrapper = new LambdaQueryWrapper<>();
        Page page = new Page<>(1, 6);
        queryWrapper.eq(Goods::getCreateAdminId,goods.getCreateAdminId());
        goodsMapper.selectPage(page,queryWrapper);
        List<GoodsDao> goodsDaos=new ArrayList<>();
        if(page.getRecords()!=null){
            for (Object record : page.getRecords()) {
                GoodsDao goodsDao = new GoodsDao();
                Goods goods1 = JSON.parseObject(JSON.toJSONString(record), Goods.class);
                BeanUtils.copyProperties(goods1,goodsDao);
                LambdaQueryWrapper<GoodsAttrs> wrapper = new LambdaQueryWrapper<>();
                LambdaQueryWrapper<GoodsAttrs> queryWrapper1 = new LambdaQueryWrapper<>();
                wrapper.eq(GoodsAttrs::getGoodsId,goods.getGoodsId());
                wrapper.eq(GoodsAttrs::getIsMany,1);
                queryWrapper1.eq(GoodsAttrs::getGoodsId,goods.getGoodsId());
                queryWrapper1.eq(GoodsAttrs::getIsMany,0);
                List<GoodsAttrs> manyAttrs = attrsMapper.selectList(wrapper);
                List<GoodsAttrs> onlyAttrs = attrsMapper.selectList(queryWrapper1);
                goodsDao.setManyAttrs(manyAttrs);
                goodsDao.setOnlyAttrs(onlyAttrs);
                goodsDaos.add(goodsDao);
            }
            return goodsDaos;
        }
        return goodsDaos;
    }
}
